package com.seezoon.application.tcp.executor;

import com.seezoon.domain.dao.mapper.DeviceAllowlistMapper;
import com.seezoon.domain.dao.mapper.DeviceInfoMapper;
import com.seezoon.domain.dao.po.DeviceAllowlistPO;
import com.seezoon.domain.dao.po.DeviceInfoPO;
import com.seezoon.domain.service.DeviceInfoService;
import com.seezoon.infrastructure.properties.AppProperties;
import com.seezoon.infrastructure.tcp.codec.JT808;
import com.seezoon.infrastructure.tcp.common.RpcContext;
import com.seezoon.infrastructure.tcp.handler.MessageHandler;
import com.seezoon.infrastructure.tcp.jt808.JT0100;
import com.seezoon.infrastructure.tcp.jt808.JT8100;
import com.seezoon.infrastructure.tcp.jt808.JT8100.ResultCode;
import java.time.Instant;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.stereotype.Component;


/**
 * @see JT808#终端注册
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class JT0100Exe implements MessageHandler<JT0100, JT8100> {

    private final AppProperties appProperties;
    private final DeviceInfoService deviceInfoService;
    private final DeviceAllowlistMapper deviceAllowlistMapper;
    private final DeviceInfoMapper deviceInfoMapper;

    @Override
    public int requestType() {
        return JT808.终端注册;
    }

    @Override
    public int responseType() {
        return JT808.终端注册应答;
    }

    public JT8100 execute(JT0100 request, RpcContext rpcContext) {
        // 该项目设备id 和sim卡是同一个，且以消息头为准
        String simNumber = rpcContext.getSerialNo();
        // 制造商ID，增加恶意注册难度
        String manufacturerId = request.getManufacturerId();

        JT8100 response = new JT8100();
        response.setResponseMsgSerialNo(rpcContext.getMsgSerialNo());

        // 白名单验证
        if (!this.registerValidate(simNumber, simNumber, manufacturerId)) {
            response.setResultCode(ResultCode.NotFoundTerminal);
            return response;
        }

        // 检查是否已注册
        DeviceInfoPO deviceInfoPO = deviceInfoMapper.selectBySimNumber(simNumber);
        if (deviceInfoPO != null) {
            response.setToken(deviceInfoPO.getAuthKey());
        } else {
            String authKey = RandomStringUtils.randomAlphanumeric(32);
            deviceInfoPO = new DeviceInfoPO();
            // 设置基本信息
            deviceInfoPO.setDeviceNo(simNumber); // 设备ID
            deviceInfoPO.setSimNumber(simNumber); // SIM卡号
            deviceInfoPO.setPlateNumber(request.getPlateNo()); // 车牌号
            deviceInfoPO.setPlateColor((byte) request.getPlateColor()); // 蓝色车牌
            deviceInfoPO.setManufacturerId(manufacturerId); // 制造商ID
            deviceInfoPO.setDeviceModel(request.getDeviceModel()); // 设备型号
            deviceInfoPO.setProvinceId((short) request.getProvinceId()); // 省
            deviceInfoPO.setCityId((short) request.getCityId()); // 市

            // 设置时间信息
            Instant now = Instant.now();
            deviceInfoPO.setLastOnlineTime(now);
            deviceInfoPO.setLastOfflineTime(now);
            deviceInfoPO.setCreateTime(now);
            deviceInfoPO.setUpdateTime(now);
            // 设置状态信息
            deviceInfoPO.setDeviceStatus(DeviceInfoPO.ONLINE); // 在线状态
            deviceInfoPO.setAuthKey(authKey); // 鉴权密钥
            deviceInfoPO.setEncryptionMode((byte) 0); // 不加密
            deviceInfoPO.setCurrentEndpoint(deviceInfoService.getCurrentEndpoint());
            deviceInfoService.register(deviceInfoPO);
            log.info("deviceNo :{},simNumber:{},manufacturerId:{} register success", simNumber, simNumber,
                    manufacturerId);
            // 返回鉴权码
            response.setToken(authKey);
        }
        response.setResultCode(ResultCode.Success);
        return response;
    }


    private boolean registerValidate(String deviceNo, String simNumber, String manufacturerId) {
        if (!appProperties.getDevice().isRegisterValidate()) {
            return true;
        }
        DeviceAllowlistPO deviceAllowlistPO = deviceAllowlistMapper.selectByDeviceNoAndSimNumberAndManufacturerId(
                deviceNo, simNumber, manufacturerId);
        // 未在白名单，不让注册
        if (deviceAllowlistPO == null) {
            log.warn("deviceId:{},simNumber:{},manufacturerId:{}, not in device allow list", deviceNo, simNumber,
                    manufacturerId);
            return false;
        }
        Instant now = Instant.now();
        Instant effectiveStart = deviceAllowlistPO.getEffectiveStart();
        Instant effectiveEnd = deviceAllowlistPO.getEffectiveEnd();

        if (effectiveStart.isAfter(now) || effectiveEnd.isBefore(now)) {
            log.warn("deviceNo:{},simNumber:{},manufacturerId:{},effective start:{},end:{} ", deviceNo, simNumber,
                    manufacturerId, effectiveStart, effectiveEnd);
            return false;
        }
        return true;
    }
}
